use chrono::Local;
use serde::{Serialize, Deserialize};
use base64::{Engine, engine::general_purpose};
use actix_web::{post, web, App, HttpRequest, HttpResponse, HttpServer, Responder};
mod storage;
mod utils;
use storage::StorageFile;

#[derive(Deserialize)]
struct PushRequest {
    tags: String,
    ctx: String,
}

#[derive(Serialize)]
struct PushResponse {
    result: bool,
    message: String,
}

#[post("/push")]
async fn push(req: HttpRequest, body: web::Json<PushRequest>) -> impl Responder {
    let current_time = Local::now();
    let connection_info = req.connection_info();
    let client_ip = connection_info.realip_remote_addr().unwrap_or("unknown");
    println!("{} - {} - {}", current_time.format("%Y-%m-%d %H:%M:%S"), client_ip, "PUSH");

    let tags = body.tags.clone();
    let data = match Engine::decode(&general_purpose::STANDARD, &body.ctx) {
        Ok(result) => result,
        Err(e) => {
            return HttpResponse::BadRequest().body(format!("Base64解码失败: {}", e));
        }
    };
    let mut sf = StorageFile::new(tags.clone());
    match sf.add_data(&data) {
        (true, _) => {
            let resp = PushResponse {
                result: true,
                message: "数据上传成功".to_string(),
            };
            HttpResponse::Ok().json(resp)
        },
        (false, Some(msg)) => {
            let resp = PushResponse {
                result: false,
                message: msg,
            };
            HttpResponse::InternalServerError().json(resp)
        },
        (false, None) => {
            let resp = PushResponse {
                result: false,
                message: "数据上传失败，未知原因！".to_string(),
            };
            HttpResponse::InternalServerError().json(resp)
        }
    }
}

#[derive(Deserialize)]
struct PullRequest {
    tags: String,
    version: u32,
}

#[derive(Serialize)]
struct PullResponse {
    result: bool,
    message: String,
    ctx: String,
}

#[post("/pull")]
async fn pull(req: HttpRequest, body : web::Json<PullRequest>) -> impl Responder {
    let current_time = Local::now();
    let connection_info = req.connection_info();
    let client_ip = connection_info.realip_remote_addr().unwrap_or("unknown");

    println!("{} - {} - {}", current_time.format("%Y-%m-%d %H:%M:%S"), client_ip, "PULL");
    let tags = body.tags.clone();
    let ver = body.version.clone();
    let sf = StorageFile::new(tags.clone());

    match sf.get_data(ver) {
        Some(buff) => {
            let resp = PullResponse {
                result: true,
                message: "数据获取成功".to_string(),
                ctx: Engine::encode(&general_purpose::STANDARD, buff),
            };
            HttpResponse::Ok().json(resp)
        },
        None => {
            let resp = PullResponse {
                result: false,
                message: "未找到该资源".to_string(),
                ctx: "".to_string(),
            };     
            HttpResponse::InternalServerError().json(resp)
        }
    }
}

#[derive(Deserialize)]
struct LastRequest {
    tags: String,
}

#[post("/last")]
async fn last(req: HttpRequest, body: web::Json<LastRequest>) -> impl Responder {
    let current_time = Local::now();
    let connection_info = req.connection_info();
    let client_ip = connection_info.realip_remote_addr().unwrap_or("unknown");

    println!("{} - {} - {}", current_time.format("%Y-%m-%d %H:%M:%S"), client_ip, "LAST");
    let tags = body.tags.clone();
    let sf = StorageFile::new(tags.clone());

    match sf.get_last_data() {
        Some(buff) => {
            let resp = PullResponse {
                result: true,
                message: "数据获取成功".to_string(),
                ctx: Engine::encode(&general_purpose::STANDARD, buff),
            };
            HttpResponse::Ok().json(resp)
        },
        None => {
            let resp = PullResponse {
                result: false,
                message: "未找到该资源".to_string(),
                ctx: "".to_string(),
            };     
            HttpResponse::InternalServerError().json(resp)
        }
    }
}

#[derive(Serialize)]
struct VersionResponse {
    result: bool,
    message: String,
    hashes: Vec<String>,
}

#[post("/versions")]
async fn verions(req: HttpRequest, body: web::Json<LastRequest>) -> impl Responder {
    let current_time = Local::now();
    let connection_info = req.connection_info();
    let client_ip = connection_info.realip_remote_addr().unwrap_or("unknown");
    println!("{} - {} - {}", current_time.format("%Y-%m-%d %H:%M:%S"), client_ip, "VERSIONS");
    let tags = body.tags.clone();
    let sf = StorageFile::new(tags.clone());
    let viles = sf.viles;
    let hashes: Vec<String> = viles.iter().map(|v| v.version.to_string()).collect();
    let resp = VersionResponse {
        result: true,
        message: "数据获取成功".to_string(),
        hashes,
    };
    HttpResponse::Ok().json(resp)
}

#[actix_web::main]
async fn main() -> std::io::Result<()> {
    
    println!("Starting VFS Server");
    println!("======================================================================");
    HttpServer::new(|| {
        App::new()
           .service(push)
           .service(pull)
           .service(last)
           .service(verions)
    })
   .bind("127.0.0.1:8080")?
   .run()
   .await
}